/*
 * 项目名称:keel-flower
 * 类名称:Oauth2Filter.java
 * 包名称:me.keelflower.filter
 *
 * 修改履历:
 *      日期                修正者      主要内容
 *      2020/12/23 21:58    liliudong      初版完成
 *
 */
package com.liliudong.keelflower.upms.admin.filter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.liliudong.keelflower.common.core.constants.Const;
import com.liliudong.keelflower.common.core.constants.HttpStatus;
import com.liliudong.keelflower.common.core.utils.R;
import com.liliudong.keelflower.upms.admin.auth.AuthorizationToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Oath2Filter
 *
 * @author liliudong 2020/12/23 21:58
 */
@Slf4j
public class AuthorizationTokenFilter extends AuthenticatingFilter {

    public AuthorizationTokenFilter() {
    }

    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
        String token = getToken(request);
        return new AuthorizationToken(token);
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        return super.isAccessAllowed(request, response, mappedValue);
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        String token = getToken(request);
        if (StrUtil.isEmpty(token)) {
            HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
            String invalidToken = JSONUtil.toJsonStr(R.fail(HttpStatus.EXPIRED_CREDENTIALS));
            httpServletResponse.getWriter().print(invalidToken);
            return false;
        }
        return super.executeLogin(request, response);
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
                                     ServletRequest request, ServletResponse response) {
        HttpStatus httpStatus;
        if (e instanceof UnknownAccountException) {
            httpStatus = HttpStatus.UNKNOWN_ACCOUNT;
        } else if (e instanceof LockedAccountException) {
            httpStatus = HttpStatus.DISABLED_ACCOUNT;
        } else if (e instanceof ExpiredCredentialsException) {
            httpStatus = HttpStatus.EXPIRED_CREDENTIALS;
        } else {
            httpStatus = HttpStatus.SYSTEM_BUSY;
        }
        try {
            log.info("登录失败:{}", httpStatus.msg);
            response.reset();
            response.resetBuffer();
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json; charset=utf-8");
            response.getWriter().write(JSONUtil.toJsonStr(R.fail(httpStatus.code, httpStatus.msg)));
        } catch (IOException ioException) {
            log.error("重定向异常", ioException);
            return false;
        }
        return super.onLoginFailure(token, e, request, response);
    }

    /**
     * 从请求头获取Token
     *
     * @param request
     * @return
     */
    private String getToken(ServletRequest request) {
        HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
        return httpServletRequest.getHeader(Const.DEFAULT_HEADER);
    }
}
